repo: use OSTREE_TIMESTAMP (=1) for checked-out files
authorMathnerd314 <mathnerd314.gph+hs@gmail.com>
Wed, 8 Jun 2016 21:39:06 +0000 (15:39 -0600)
committerAtomic Bot <atomic-devel@projectatomic.io>
Thu, 9 Jun 2016 18:04:55 +0000 (18:04 +0000)
1 is a better choice than 0 because some programs use 0
as a special value; for example, GNU Tar warns of an
"implausibly old timestamp" with 0.

Closes: #330
Approved by: cgwalters

docs/manual/repo.md
src/libostree/ostree-repo-checkout.c
src/libostree/ostree-repo-commit.c
src/libostree/ostree-repo-libarchive.c
src/libostree/ostree-repo-private.h
src/libostree/ostree-repo.c
tests/basic-test.sh

index d6f670907b4064cffe88b35590a41edbd3fcd2dc..bce7e0c9c7e3ce61f1e36f548a3c3f820a2f30c8 100644 (file)
@@ -47,6 +47,22 @@ payload sections.  The header contains uid, gid, mode, and symbolic
 link target (for symlinks), as well as extended attributes.  After the
 header, for regular files, the content follows.
 
+The OSTree data format intentionally does not contain timestamps. The reasoning
+is that data files may be downloaded at different times, and by different build
+systems, and so will have different timestamps but identical physical content.
+These files may be large, so most users would like them to be shared, both in
+the repository and between the repository and deployments.
+
+This could cause problems with programs that check if files are out-of-date by
+comparing timestamps. For Git, the logical choice is to not mess with
+timestamps, because unnecessary rebuilding is better than a broken tree.
+However, OSTree has to hardlink files to check them out, and commits are assumed
+to be internally consistent with no build steps needed. For this reason, OSTree
+acts as though all timestamps are set to time_t 1, so that comparisons will be
+considered up-to-date. 1 is a better choice than 0 because some programs use 0
+as a special value; for example, GNU Tar warns of an "implausibly old time
+stamp" with 0.
+
 # Repository types and locations
 
 Also unlike git, an OSTree repository can be in one of three separate
index 95d3747bf8abea336caf619c63b9ea63c8f628ff..227227b657cc63f2c1406c196e9bf80afcf72a53 100644 (file)
@@ -752,12 +752,12 @@ checkout_tree_at (OstreeRepo                        *self,
         }
     }
 
-  /* Set directory mtime to 0, so that it is constant for all checkouts.
+  /* Set directory mtime to OSTREE_TIMESTAMP, so that it is constant for all checkouts.
    * Must be done after setting permissions and creating all children.
    */
   if (!did_exist)
     {
-      const struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, } };
+      const struct timespec times[2] = { { OSTREE_TIMESTAMP, UTIME_OMIT }, { OSTREE_TIMESTAMP, 0} };
       do
         res = futimens (destination_dfd, times);
       while (G_UNLIKELY (res == -1 && errno == EINTR));
index 6cb46ca987d9692ebdecda341af4b3f39aa38fec..6166c65237dcdb812c546a76ef52d68c3de8e8ab 100644 (file)
@@ -210,7 +210,6 @@ commit_loose_object_trusted (OstreeRepo        *self,
   else
     {
       int res;
-      struct timespec times[2];
 
       if (objtype == OSTREE_OBJECT_TYPE_FILE && self->mode == OSTREE_REPO_MODE_BARE)
         {
@@ -266,12 +265,9 @@ commit_loose_object_trusted (OstreeRepo        *self,
         {
           /* To satisfy tools such as guile which compare mtimes
            * to determine whether or not source files need to be compiled,
-           * set the modification time to 0.
+           * set the modification time to OSTREE_TIMESTAMP.
            */
-          times[0].tv_sec = 0; /* atime */
-          times[0].tv_nsec = UTIME_OMIT;
-          times[1].tv_sec = 0; /* mtime */
-          times[1].tv_nsec = 0;
+          const struct timespec times[2] = { { OSTREE_TIMESTAMP, UTIME_OMIT }, { OSTREE_TIMESTAMP, 0} };
           do
             res = futimens (fd, times);
           while (G_UNLIKELY (res == -1 && errno == EINTR));
index 0d62124dc61558f486e0ae6b9f3c054c5d8ee92e..45427ef774bda20be24abacce9feea7c88cf9ec8 100644 (file)
@@ -982,9 +982,9 @@ file_to_archive_entry_common (GFile         *root,
     }
 
   archive_entry_update_pathname_utf8 (entry, pathstr);
-  archive_entry_set_ctime (entry, ts, 0);
-  archive_entry_set_mtime (entry, ts, 0);
-  archive_entry_set_atime (entry, ts, 0);
+  archive_entry_set_ctime (entry, ts, OSTREE_TIMESTAMP);
+  archive_entry_set_mtime (entry, ts, OSTREE_TIMESTAMP);
+  archive_entry_set_atime (entry, ts, OSTREE_TIMESTAMP);
   archive_entry_set_uid (entry, g_file_info_get_attribute_uint32 (file_info, "unix::uid"));
   archive_entry_set_gid (entry, g_file_info_get_attribute_uint32 (file_info, "unix::gid"));
   archive_entry_set_mode (entry, g_file_info_get_attribute_uint32 (file_info, "unix::mode"));
index 62a3c8f6237c8b0570b97513033f6736ef4382ec..35b05c76582425e3003031cd012cabd9075a2264 100644 (file)
@@ -36,6 +36,8 @@ G_BEGIN_DECLS
 #define _OSTREE_SUMMARY_CACHE_DIR "summaries"
 #define _OSTREE_CACHE_DIR "cache"
 
+#define OSTREE_TIMESTAMP (1)
+
 typedef enum {
   OSTREE_REPO_TEST_ERROR_PRE_COMMIT = (1 << 0)
 } OstreeRepoTestErrorFlags;
index 6af5d8e65076799989d5168a7d22c2221bba3075..fd02833a3744c77d0b4f159513bc9c666dfe7e6a 100644 (file)
@@ -942,6 +942,14 @@ ostree_repo_is_writable (OstreeRepo *self,
   return self->writable;
 }
 
+/**
+ * _ostree_repo_update_mtime:
+ * @self: Repo
+ * @error: a #GError
+ *
+ * Bump the mtime of the repository so that programs
+ * can detect that the refs have updated.
+ */
 gboolean
 _ostree_repo_update_mtime (OstreeRepo        *self,
                            GError           **error)
index 93f67f178d0c373a4c9ad6f0a50a4386692472bc..0fe372dc870505b3e904879876795e290bc4695c 100755 (executable)
@@ -386,9 +386,9 @@ else
     $OSTREE checkout test2 test2-checkout
 fi
 stat '--format=%Y' test2-checkout/baz/cow > cow-mtime
-assert_file_has_content cow-mtime 0
+assert_file_has_content cow-mtime 1
 stat '--format=%Y' test2-checkout/baz/deeper > deeper-mtime
-assert_file_has_content deeper-mtime 0
+assert_file_has_content deeper-mtime 1
 echo "ok content mtime"
 
 cd ${test_tmpdir}